import axios from "axios";
import debug from "debug";

const log = debug("gogs:client");

export function version(): string {
  return "0.13.0";
}

export interface ClientOptions {
  url: string;
  token: string;
}

/**
 * Response type for axios requests
 */
export type ResponseType = "json" | "text" | "arraybuffer" | "blob";

/**
 * Client represents a Gogs API client.
 */
export class Client {
  private url: string;
  private accessToken: string;
  private axiosInstance: typeof axios;

  /**
   * Creates a new Gogs API client
   */
  constructor(options: ClientOptions) {
    this.url = options.url.endsWith("/") 
      ? options.url.slice(0, -1) 
      : options.url;
    this.accessToken = options.token;
    this.axiosInstance = axios;
  }

  /**
   * Set custom axios instance
   */
  setAxiosInstance(instance: typeof axios): void {
    this.axiosInstance = instance;
  }

  /**
   * Make a request to the Gogs API
   */
  async doRequest<T>(
    method: string, 
    path: string, 
    headers: Record<string, string> = {}, 
    body?: unknown,
    responseType: ResponseType = "json"
  ): Promise<T> {
    try {
      const response = await this.axiosInstance({
        method,
        url: `${this.url}/api/v1${path}`,
        headers: {
          Authorization: `token ${this.accessToken}`,
          ...headers,
        },
        data: body,
        responseType,
      });
      
      return response.data as T;
    } catch (error) {
      if (axios.isAxiosError(error)) {
        if (error.response) {
          const status = error.response.status;
          const apiUrl = `${this.url}/api/v1${path}`;
          if (status === 403) {
            throw new Error(`403 Forbidden - ${apiUrl}`);
          } else if (status === 404) {
            throw new Error(`404 Not Found - ${apiUrl} - ${JSON.stringify(error.response.data)}`);
          } else if (status >= 400) {
            const data = error.response.data as { message?: string };
            throw new Error(data.message || `HTTP Error: ${status} - ${apiUrl}:${JSON.stringify(error.response.data)}`);
          }
        }
      }
      throw error;
    }
  }
} 